﻿/*Copyright (C) 2010-2012 RAAFCOM B.V. All rights reserved.

This file is part of Velsto and may be used under the terms of:
The GNU General Public License version 3 or higher, as published by
the Free Software Foundation.

This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.*/
// ******************************************************************************************************
// <copyright file="select.cs" company="Caroso.inc">
//     Copyright (c) Carlos Osorio All rights reserved.
// </copyright>
// ******************************************************************************************************
// The contents of this file are subject to the Mozilla Public License Version 1.1 (the "License"); 
// you may not use this file except in compliance with the License. You may obtain a copy of the License at 
// http:// www.mozilla.org/MPL/ 
// Software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTY OF 
// ANY KIND, either express or implied. See the License for the specificlanguage governing rights and 
// limitations under the License. 
// 
// 
// 
// The Initial Developer of this version of the Original Code is carlos Osorio carosocali@gmail.com
// 
// Contributor(s): (Open source contributors should list themselves and their modifications here). 
// Change Log: 
// Date           Changed By      Notes
// 22 Nov 2010    Carlos Osorio   Test in StyleCop
// 28 Apr 2012    Maurits van Ravesteijn(RAAFCOM BV) Velsto version reading xyz file
// ******************************************************************************************************

namespace Velsto
{
    using System;
    using System.Collections;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Linq;
    using System.Text;
    using System.Windows.Forms;
    using MapWindow.Interfaces;

    /// <summary>
    /// Create the Form
    /// </summary>
    public partial class Select : Form
    {
        /// <summary>
        /// Definition of delegate with FormMain
        /// </summary>
        private SelectDelegate selDel;
        private SimulationEntity se;
        private MapWinGIS.Shapefile shpResid;


        /// <summary>
        /// Denifinition of enviroment Mapwindow
        /// </summary>
        private IMapWin myMapWin;

        /// <summary>
        /// Shapefile uses in the interpolation
        /// </summary>
        private MapWinGIS.Shapefile shapeLayer;
        
        /// <summary>
        /// Identification of the field that contain the Z value
        /// </summary>
        private int idField;

        /// <summary>
        /// Kriging object
        /// </summary>
        private Kriging mkriging;

        /// <summary>
        /// Manage the display of the all point in the semivariogram
        /// </summary>
        private bool optGra = false;

        /// <summary>
        /// Manage the display of the semivariomgram by Lags
        /// </summary>
        private bool optGraL = false;

        /// <summary>
        /// Manages the display of the theoretical semivariogram
        /// </summary>
        private bool showModel = false;

        /// <summary>
        /// Initializes a new instance of the Select class
        /// </summary>
        public Select()
        {
            this.InitializeComponent();
        }

        /// <summary>
        /// Initializes a new instance of the Select class
        /// </summary>
        /// <param name="mapWin">Global variable of Mapwin</param>
        public Select(IMapWin mapWin)
        {
            this.myMapWin = mapWin;
            this.InitializeComponent();
			//this.pathfile.Text = System.IO.Path.GetTempPath() + "krigtemp.bil";
        }

        public Select(SelectDelegate sd1, MapWinGIS.Shapefile shp1, ref SimulationEntity se2)
        {
            selDel = sd1;
            se = se2;
            shpResid = new MapWinGIS.Shapefile();
            shpResid = shp1;
            //MessageBox.Show(shpResid.NumShapes.ToString());
            this.InitializeComponent();
            this.groupBox1.Enabled = true;
            this.groupBox2.Enabled = false;
            this.groupBox3.Enabled = false;
            this.groupBox4.Enabled = false;
            comboBox3.Items.Add("GSLIB Simple Kriging");
            comboBox3.Items.Add("GSLIB Ordinary Kriging");
            comboBox3.SelectedIndex = 0;
            se.WellResKrigingType = Constants.KRIGINGTYPE_SIMPLE;
        }

        public Select(ref SimulationEntity se2)
        {
            se = se2;
            this.InitializeComponent();
            this.groupBox1.Enabled = true;
            this.groupBox2.Enabled = false;
            this.groupBox3.Enabled = false;
            this.groupBox4.Enabled = false; 
            comboBox3.Items.Add("Simple Kriging");
            comboBox3.Items.Add("Ordinary Kriging");
            comboBox3.SelectedIndex = 0;
        }




        /// <summary>
        ///  Load the form call Select
        /// </summary>
        /// <param name="sender">Sender (object) </param>
        /// <param name="e">Event arguments</param>
        private void Select_Load(object sender, EventArgs e)
        {
            this.mkriging = new Kriging(shpResid);
            this.pictureBox1.Visible = true;
            this.listBox1.SelectedIndex = 2;
            /*for (int i = 0; i < this.myMapWin.Layers.NumLayers; i++)
            {
                if (this.myMapWin.Layers[i].LayerType == eLayerType.PointShapefile)
                {
                    this.comboBox1.Items.Add(this.myMapWin.Layers[i].Name.ToString());
                }
            }*/
            ToolTip tt1 = new ToolTip();
            tt1.SetToolTip(butKrig_resid, "Map of kriged residuals using model variogram");
            ToolTip tt2 = new ToolTip();
            tt2.SetToolTip(butZ_well, "Depth map with kriged residuals added");
            ToolTip tt3 = new ToolTip();
            tt3.SetToolTip(butZdev_well, "Uncertainty map tied to wells using relative kriging variance");
            }
        
        /// <summary>
        /// Generate a graphic of a semivariogram with all points by default
        /// </summary>
        private void Create_graphic() 
        {
            this.CreateGraphicPar((float)this.mkriging.MaxDistance, (float)this.mkriging.MaxVariance, "ALL", 0, 0);
        }
        
        /// <summary>
        /// Create a graph of a semivariance
        /// </summary>
        /// <param name="maxD">Max. distance in the semivariogram</param>
        /// <param name="maxS">Max semivariance</param>
        /// <param name="typeG">Type of displaying</param>
        /// <param name="lag">length of the lag</param>
        /// <param name="nlags">Number of the lags</param>
        private void CreateGraphicPar(float maxD, float maxS, string typeG, double lag, int nlags) 
        { 
         ////Create an instance of GraphicSemivariogram.cs file.
            GraphicSemivariogram graphicSemivariogram = new GraphicSemivariogram();
            ////Set the height for the graph image.
            graphicSemivariogram.Height = 200;
            ////Set the width for the graph image.
            graphicSemivariogram.Width = 550;
            ////Set the Slices(partition in Axis) for X and Y Axis.
            graphicSemivariogram.XSlice = 35;
            graphicSemivariogram.YSlice = 35;
            ////Set the Title for both Axis.
            graphicSemivariogram.XAxisText = "Distance (m)";
            graphicSemivariogram.YAxisText = "Semiv.";
            graphicSemivariogram.XrealValue = (float)(maxD * 50) / (550 - (2 * 35));
            graphicSemivariogram.YrealValue = (float)(maxS * 50) / (200 - (2 * 35));
            ////Set the Graph Title.;
            graphicSemivariogram.Title = "Semivariogram";
            ////Set the Backcolor and forecolor for the graph title.
            graphicSemivariogram.TitleBackColor = Color.White;
            graphicSemivariogram.TitleForeColor = Color.Black;
            ////Initialize the graph object to draw.
            graphicSemivariogram.InitializeGraph();
            ////Create two array list to  store the points.
            //// string pp;
            ////Create Firstline
            //// GraphicSemivariogram.CreateGraph(Color.LightCyan);
            ArrayList arX;
            ArrayList arY;
            //// Boolean t = false;
            if (typeG == "ALL")
            {
                arX = new ArrayList();
                arY = new ArrayList();
                
                graphicSemivariogram.XAxis = this.mkriging.Distances();
                graphicSemivariogram.YAxis = this.mkriging.SemiVariances();
                //MessageBox.Show("YAXIS npoints " + graphicSemivariogram.YAxis.Count.ToString());
            }
            else 
            {
                this.mkriging.CalculateLags(lag, nlags, out arX, out arY);
                graphicSemivariogram.XAxis = arX;
                graphicSemivariogram.YAxis = arY;
            }

            ArrayList arx1;
            ArrayList ary1;
            if (this.showModel) 
            {
                this.mkriging.CalculateModelGraphic(out arx1, out ary1);
                graphicSemivariogram.X1Axis = arx1;
                graphicSemivariogram.Y1Axis = ary1;
                graphicSemivariogram.CreateLines();
            }
            
            ////Create Second Line.
           graphicSemivariogram.CreateGraph(Color.Red);
            Bitmap bmp = graphicSemivariogram.GetGraph();
            this.pictureBox1.Image = bmp;
            ////bmp.Save(Response.OutputStream,ImageFormat.Jpeg);
        }
       
        /// <summary>
        ///  This function is executed after selection of un item in the ComboBox1
        /// </summary>
        /// <param name="sender">Object (sender)</param>
        /// <param name="e">Events arguments</param>
        private void ComboBox1_SelectedIndexChanged(object sender, EventArgs e)
        {
            bool info = false;
            this.showModel = false;
            for (int i = 0; i < this.myMapWin.Layers.NumLayers; i++)
            {
                if (this.myMapWin.Layers[i].LayerType == eLayerType.PointShapefile)
                {
                    if (this.myMapWin.Layers[i].Name.ToString() == this.comboBox1.Text) 
                    {
                        this.shapeLayer = new MapWinGIS.Shapefile();
                        this.shapeLayer.Open(this.myMapWin.Layers[i].FileName.ToString(), null);
                        for (int j = 0; j < this.shapeLayer.NumFields; j++) 
                        {
                            if (this.shapeLayer.get_Field(j).Type.Equals(MapWinGIS.FieldType.DOUBLE_FIELD) | this.shapeLayer.get_Field(j).Type.Equals(MapWinGIS.FieldType.INTEGER_FIELD))
                            {
                            this.comboBox2.Items.Add(this.shapeLayer.get_Field(j).Name.ToString());
                            info = true;
                            }
                        }
                    }
                }
                ////pictureBox1.Visible = true;
            }

            if (info) 
            {
                this.groupBox1.Enabled = true;
                this.groupBox2.Enabled = false;
                this.groupBox3.Enabled = false;
                this.groupBox4.Enabled = false;
               //// pictureBox1.Visible = false;
            }
        }

        /// <summary>
        ///  This function is executed after selection of un item in the ComboBox2
        /// </summary>
        /// <param name="sender">Object (sender)</param>
        /// <param name="e">Events arguments</param>
        private void ComboBox2_SelectedIndexChanged(object sender, EventArgs e)
        {
            this.showModel = false;
            if (this.comboBox2.Text != string.Empty)
            {
                this.idField = 0;
                for (int j = 0; j < this.shapeLayer.NumFields; j++)
                {
                    if (this.shapeLayer.get_Field(j).Name.ToString() == this.comboBox2.Text)
                    {
                        this.idField = j;
                    }
                }

                this.mkriging = new Kriging(this.shapeLayer, this.idField);
                this.pictureBox1.Visible = true;
            }
            else 
            {
                this.groupBox2.Enabled = false;
                this.groupBox3.Enabled = false;
                this.groupBox4.Enabled = false;
                this.pictureBox1.Visible = false;
            }
        }

        /// <summary>
        ///  This function is executed after click over button VerSemi
        /// </summary>
        /// <param name="sender">Object (sender)</param>
        /// <param name="e">Events arguments</param>
        private void VerSemi_Click(object sender, EventArgs e)
        {
            this.groupBox2.Enabled = true;
            this.groupBox3.Enabled = true;
            if (!this.showModel)
            {
                this.mtxrange.Text = Math.Round(this.mkriging.MaxDistance / 2, 2).ToString();
                this.mtxc1.Text = Math.Round(this.mkriging.MaxVariance / 2, 4).ToString();
                this.mtxc0.Text = "0";
                se.WellResVarioC0 = 0.0;
                se.WellResVarioC1 = this.mkriging.MaxVariance/2.0;
                se.WellResVarioRange = this.mkriging.MaxDistance / 2.0;
            }
                        
            if (this.radioButton1.Checked)
            {
                if (this.optGra == false)
                {
                    this.Create_graphic();
                    this.txbmDist.Text = Math.Round(this.mkriging.MaxDistance, 2).ToString();
                    this.txbmVar.Text = Math.Round(this.mkriging.MaxVariance, 4).ToString();
                    this.txblag.Enabled = false;
                    this.txbnLags.Enabled = false;
                }
                else 
                {
                    this.CreateGraphicPar(float.Parse(this.txbmDist.Text), float.Parse(this.txbmVar.Text), "ALL", 0, 0);
                }
            }
            else 
            {
                if (this.optGraL == false)
                {
                    this.txblag.Enabled = true;
                    this.txbnLags.Enabled = true;
                    this.CreateGraphicPar((float)this.mkriging.MaxDistance, (float)this.mkriging.MaxVariance, "Lag", this.mkriging.MaxDistance * 0.9 / 12, 12);
                    this.txbmDist.Text = Math.Round(this.mkriging.MaxDistance, 2).ToString();
                    this.txbmVar.Text = Math.Round(this.mkriging.MaxVariance, 4).ToString();
                    this.txblag.Text = Math.Round(this.mkriging.MaxDistance * 0.9 / 12, 2).ToString();
                    this.txbnLags.Text = "12";
                }
                else 
                {
                    this.CreateGraphicPar(float.Parse(this.txbmDist.Text), float.Parse(this.txbmVar.Text), "Lag", double.Parse(this.txblag.Text), int.Parse(this.txbnLags.Text));
                }
            }
            //double height = Math.Abs(this.shapeLayer.Extents.yMax - this.shapeLayer.Extents.yMin);
            //double width = Math.Abs(this.shapeLayer.Extents.xMax - this.shapeLayer.Extents.xMin);
            double defaultCellSize = -1;
            if (se.MapNrows <= se.MapNcols)
            {
                defaultCellSize = (se.MapNrows * se.MapCellsize) / 50;
            }
            else
            {
                defaultCellSize = (se.MapNcols * se.MapCellsize) / 50;
            }

            //this.resolution.Text = Math.Round(defaultCellSize, 4).ToString();
        }

        /// <summary>
        ///  This function is executed after click over button Button1 (apply the model)
        /// </summary>
        /// <param name="sender">Object (sender)</param>
        /// <param name="e">Events arguments</param>
        private void Button1_Click(object sender, EventArgs e)
        {
            IKrigingModel model;
            if ((this.mtxrange.Text != string.Empty) && (this.mtxc0.Text != string.Empty) && (this.mtxc1.Text != string.Empty))
            {
                if (double.Parse(this.mtxrange.Text) == 0)
                {
                    MessageBox.Show("Range must be greater than zero");
                }
                else 
                {
                    switch (this.listBox1.SelectedItems[0].ToString())
                    {
                        case "Gaussian":
                            model = new ModelGaussian();
                            se.WellResVarioModel = Constants.VAR_MODEL_GAUSS;
                            break;
                        case "Circular":
                            model = new ModelCircular();
                            break;
                        case "Exponential":
                                  model = new ModelExponential();
                                  se.WellResVarioModel = Constants.VAR_MODEL_EXP;
                                 break;
                        case "Spherical":
                                 model = new ModelSpherical();
                                 se.WellResVarioModel = Constants.VAR_MODEL_SPHER;
                                 break;
                        case "Lineal":
                                 model = new ModelLineal();
                                 break;
                        default:
                                 model = new ModelSpherical();
                                 se.WellResVarioModel = Constants.VAR_MODEL_SPHER;
                                 break;
                    }

                    model.C0 = double.Parse(this.mtxc0.Text);
                    model.C1 = double.Parse(this.mtxc1.Text);
                    model.Range = double.Parse(this.mtxrange.Text);
                    se.WellResVarioC0 = model.C0;
                    se.WellResVarioC1 = model.C1;
                    se.WellResVarioRange = model.Range;

                    this.mkriging = new Kriging(shpResid,model);

                    this.showModel = true;
                    this.VerSemi_Click(sender, e);
                    this.groupBox4.Enabled = true;
                }
            }
        }

        /// <summary>
        /// Apply the chages in the graph (Max, min..)
        /// </summary>
        /// <param name="sender">Object (sender)</param>
        /// <param name="e">Events arguments</param>
        private void Apply_Click(object sender, EventArgs e)
        {
            if (this.radioButton1.Checked)
            {
                if (this.optGra == false)
                {
                    this.Create_graphic();
                    this.txbmDist.Text = Math.Round(this.mkriging.MaxDistance, 2).ToString();
                    this.txbmVar.Text = Math.Round(this.mkriging.MaxVariance, 4).ToString();
                    this.txblag.Enabled = false;
                    this.txbnLags.Enabled = false;
                }
                else
                {
                    this.CreateGraphicPar(float.Parse(this.txbmDist.Text), float.Parse(this.txbmVar.Text), "ALL", 0, 0);
                }
            }
            else
            {
                if (this.optGraL == false)
                {
                    this.txblag.Enabled = true;
                    this.txbnLags.Enabled = true;
                    this.CreateGraphicPar((float)this.mkriging.MaxDistance, (float)this.mkriging.MaxVariance, "Lag", this.mkriging.MaxDistance * 0.9 / 12, 12);
                    this.txbmDist.Text = Math.Round(this.mkriging.MaxDistance, 2).ToString();
                    this.txbmVar.Text = Math.Round(this.mkriging.MaxVariance, 4).ToString();
                    this.txblag.Text = Math.Round(this.mkriging.MaxDistance * 0.9 / 12, 2).ToString();
                    this.txbnLags.Text = "12";
                }
                else
                {
                    this.CreateGraphicPar(float.Parse(this.txbmDist.Text), float.Parse(this.txbmVar.Text), "lag", double.Parse(this.txblag.Text), int.Parse(this.txbnLags.Text));
                }
            }
        }

        /// <summary>
        /// Evaluate if there is any change in the value of the Variance
        /// </summary>
        /// <param name="sender">Object (sender)</param>
        /// <param name="e">Events arguments</param>
        private void Txb_mVar_TextChanged(object sender, EventArgs e)
        {
            this.optGra = true;
        }

        /// <summary>
        /// Evaluate if there is any change in the value of the Distance
        /// </summary>
        /// <param name="sender">Object (sender)</param>
        /// <param name="e">Events arguments</param>
        private void Txb_mDist_TextChanged(object sender, EventArgs e)
        {
            this.optGra = true;
        }

        /// <summary>
        /// Evaluate if there is any change in the value of the lag
        /// </summary>
        /// <param name="sender">Object (sender)</param>
        /// <param name="e">Events arguments</param>
        private void Txb_lag_TextChanged(object sender, EventArgs e)
        {
            this.optGraL = true;
        }

        /// <summary>
        /// Evaluate if there is any change in the value of the number of lags
        /// </summary>
        /// <param name="sender">Object (sender)</param>
        /// <param name="e">Events arguments</param>
        private void Txb_nLags_TextChanged(object sender, EventArgs e)
        {
            this.optGraL = true;
        }

        /// <summary>
        /// Evaluate if there is any change in the value of the lag
        /// </summary>
        /// <param name="sender">Object (sender)</param>
        /// <param name="e">Events arguments</param>
        private void Generate_Click(object sender, EventArgs e)
        {
            selDel(shpResid, se);
            return;
            ////ShapeLayer.Projection.ToString()
            /*this.Cursor = Cursors.WaitCursor;
            string path=this.shapeLayer.Projection;
            try
            {
                this.mkriging.Surface(this.shapeLayer.Extents, double.Parse(this.resolution.Text), @path, -32768, @path, int.Parse(this.nPn.Text));
               }
            catch
            {
            this.mkriging.outGrid.Close();
            MessageBox.Show("There is a problem in the surface creation");
            this.Cursor = Cursors.Default;
            return;
            }



            try
            {
                MapWinGIS.GridColorScheme scheme = new MapWinGIS.GridColorScheme();
                scheme.NoDataColor = System.Convert.ToUInt32(true);
                scheme.UsePredefined((double)this.mkriging.outGrid.Minimum,(double) this.mkriging.outGrid.Maximum, MapWinGIS.PredefinedColorScheme.ValleyFires);
                this.myMapWin.Layers.Add(ref this.mkriging.outGrid,scheme, "Predicted Kriging Surface");
            } 
            catch
            {
                MessageBox.Show("The surface was created succesfully. !Add it manually!");
                this.Cursor = Cursors.Default;
                return;
                
            }

            MessageBox.Show("The surface was created succesfully.");
            this.Cursor = Cursors.Default;
            return;*/
            
            ////  MyMapWin.Layers.Add(ref newgrid,"Interpolation Kriging");
        }

        /// <summary>
        /// Action to save the file
        /// </summary>
        /// <param name="sender">Object (sender)</param>
        /// <param name="e">Events arguments</param>
        private void Button3_Click(object sender, EventArgs e)
        {
            SaveFileDialog saveDialog = new SaveFileDialog();
            saveDialog.Filter = "Bil (*.bil)|*.bill| asc (*.asc)|*.asc";

            if (saveDialog.ShowDialog() == DialogResult.OK)
            {
                //this.pathfile.Text = saveDialog.FileName;
            }
        }

        /// <summary>
        /// It is execute when there is a change in the lisbox1
        /// </summary>
        /// <param name="sender">Object (sender)</param>
        /// <param name="e">Events arguments</param>
        private void ListBox1_SelectedIndexChanged(object sender, EventArgs e)
        {
        }

        private void butZ_well_Click(object sender, EventArgs e)
        {
            se.MapType = Constants.MAP_Z_WELL;
            selDel(shpResid, se);
            return;
        }

        private void butWell_bull_Click(object sender, EventArgs e)
        {
            se.MapType = Constants.MAP_WELL_BULL;
            selDel(shpResid, se);
            return;
        }

        private void butZdev_well_Click(object sender, EventArgs e)
        {
            se.MapType = Constants.MAP_ZDEV_WELL2;
            selDel(shpResid, se);
            return;
        }

        private void butKrig_resid_Click(object sender, EventArgs e)
        {
            se.MapType = Constants.MAP_RES_KRIG;
            selDel(shpResid, se);
            return;
        }

        private void comboBox3_SelectedIndexChanged(object sender, EventArgs e)
        {
            se.WellResKrigingType = comboBox3.SelectedIndex + 1;
        }
    }
}
